Before the Crackdown
For a long time MLB teams had what some would call a gentleman’s agreement over utilizing foreign substances. Initially this started as a way for pitchers to better their grip on the ball when they pitched. Now, it’s gotten to the point that the foreign substances are so sticky that rather than just helping pitchers grip the ball, it’s making the ball stick to their hand for longer, thus increasing the spin rate of the ball and making it harder to hit. As the spin of the ball increases the general location in which the ball is getting thrown is higher, adding to the difficulties hitters are already facing. The spin on pitches like the 4-seam fastballs is a back spin, which opposes the downward force of gravity on the ball (think of the term ‘rising fastball’).
The MLB made a decision coming out against foreign substances by stating that starting on June 1st umpires will begin checking for pitchers using foreign substances and on June 16th announced players caught using them will be removed from the game, placed on a 10 game suspension, and fined. Many people have argued that these statements won’t deter pitchers from utilizing foreign substances. Yet many analysts have been saying spin rates going down and batting averages going up. In this notebook we will be examining the affect of the MLB’s new implementation and examining changes with individual players.
All the data included has been provided by Baseball Savant found through utilizing the search feature and Baseball Reference (linked when referenced).
Velocity vs Spin Rate
It’s important to note that generally as increases velocity so does spin rate. In this section we will be comparing pitchers spin rates vs velocities before and after June 1st.
library(ggplot2) ## loading packages
library(ggExtra)
library(dplyr)
library(tidyverse)
library(lubridate)
Attaching package: ‘lubridate’
The following objects are masked from ‘package:base’:
date, intersect, setdiff, union
b4 <-
read.csv('b4June1.csv')
b4
aft <-
read.csv('aftJune1st.csv')
aft
b4gr <-
b4 %>%
ggplot(aes(x = velocity, y = spin_rate, color = total_pitches)) +
geom_point(stat = 'identity') +
xlab('Velocity (mph)') +
ylab('Spin Rate (rpm)') +
ggtitle('Spin Rate VS Velocity Prior to June 1st') +
labs(color = 'Total Pitches')
##using ggExtra package to add histograms to show the distribution of data within the scatterplot
p1 <-
ggMarginal(b4gr, type = 'histogram')
p1


aftgr <-
aft %>%
ggplot(aes(x = velocity, y = spin_rate, color = total_pitches)) +
geom_point(stat = 'identity') +
xlab('Velocity (mph)') +
ylab('Spin Rate (rpm)') +
ggtitle('Spin Rate VS Velocity After June 1st') +
labs(color = 'Total Pitches')
p2 <-
ggMarginal(aftgr, type = 'histogram')
p2

The graph of the data before June 1st shows that generally pitchers average spin rates are concentrated between 2200 rpm and 2600 rpm and the velocities range from the upper 80s to mid 90s.
The graph of the data following June 1st, displays a higher conglomeration of pitchers with average pitches between 2000 and 2500 rpm and less outliers with spin rates above 2750 rpm. With velocities concentrated between the upper 80’s and lower 90’s and spin rates between 2000 rpm and 2500 rpm.
Upon further inspection of the scatterplot it appears that most of the outliers are darker shaded dots representing pitcher who’ve thrown between 1 and 250 pitches. Because this data is based on averages and smaller sample sizes are generally less representative of the individual. This prompted me to see if there was a difference when if I increased the minimum number of pitches to at least 250.
b4abv <-
b4%>%
filter(total_pitches > 249)
b4abv
aftabv <-
aft%>%
filter(total_pitches > 249)
aftabv
babvgr <-
b4abv %>%
ggplot(aes(x = velocity, y = spin_rate, color = total_pitches)) +
geom_point(stat = 'identity') +
xlab('Velocity (mph)') +
ylab('Spin Rate (rpm)') +
labs(color = 'Total Pitches',
title = 'Spin Rate vs Velocity Before June 1st',
caption = 'For pitchers with over 250 pitches') +
scale_color_viridis_c()
g1 <-
ggMarginal(babvgr, type = 'histogram')
g1


afabvgr <-
aftabv %>%
ggplot(aes(x = velocity, y = spin_rate, color = total_pitches)) +
geom_point(stat = 'identity') +
xlab('Velocity (mph)') +
ylab('Spin Rate (rpm)') +
labs(color = 'Total Pitches',
title = 'Spin Rate vs Velocity After June 1st',
caption = 'For pitchers with over 250 pitches') +
scale_color_viridis_c()
k1 <-
ggMarginal(afabvgr, type = 'histogram')
k1

Here we can see a more notable difference between average spin rates and velocities. Prior to June 1st we can see that average velocities were generally between the upper 80s and mid 90s, with spin rates ranging between 2100 and 2600 rpm. The extremes included 5 pitchers with spin rates above 2750 rpm and 20 pitchers above 95 mph. In contrast we can see that after June 1st, velocities are concentrated between the mid 80s to lower 90’s and spin rates between 2000 and 2500 rpm. The extremes here now only include 1 pitcher with an average spin rate above 2750 and 3 pitchers above 95 mph. Additionally the frequency distribution of the velocities changed from left skew to a normal distribution. Whereas the frequency distribution of the spin rates went from bi-modal to a normal distribution following June 1st.
Individual Pitcher Changes
In this section we will be examining a change in spin rate, velocity, and overall performance (if any) between specific pitchers: Trevor Bauer, Gerrit Cole, Jacob deGrom, and Garrett Richards.
Trevor Bauer
It’s hard to have any conversation about foreign substances in baseball without mentioning Trevor Bauer. From being someone who initially spoken against foreign substances and once even stating that they could be more powerful than steroids, to now being accused of having the most effective sticky substance combination in the league, Bauer’s name has been brought up a lot. Considering recent events regarding Bauer’s arrest and allegation, the data available is more limited than with other players.
bauer <- ## downloaded from Baseball Savant
read.csv('bauer advanced stats.csv')
bauer
num <- ## finding counts of each pitch type
bauer %>%
group_by(pitch_name) %>%
summarise(count = n())
num
From this data we can see that during the month of June, Bauer’s most utilized pitches were the fastball, cutter, and slider.
June 28th
tbju28 <-
bauer %>%
filter(game_date == '2021-06-28')
tbju28
tb2avgs <- ## finding game averages from the June 28th game
tbju28 %>%
select(pitch_name, release_speed, release_spin_rate) %>%
group_by(pitch_name) %>%
summarise(avgspeed = mean(release_speed, na.rm = TRUE), avgspin = mean(release_spin_rate, na.rm = TRUE), count = n()) %>%
arrange(pitch_name)
tb2avgs
From this we can see that Bauer’s fastest average pitches are his sinker, fastball, and changeup. His pitches with the highest spin rates are the knuckle curve, slider, cutter, and fastball, all with spin rates all well above the average spin rate of 2280 rpm.
Bauer’s most utilized pitches this game:
Cutter (medium velocity & high spin rate)
Slider (low velocity & high spin rate)
Fastball (high velocity & spin rate)
note: Bauer’s ERA during this game was 2.59 Baseball Reference
June 6th
tbju6 <-
bauer %>%
filter(game_date == '2021-06-06')
tbju6
tb6avgs <-
tbju6%>%
select(pitch_name, release_speed, release_spin_rate) %>%
group_by(pitch_name) %>%
summarise(avgspeed = mean(release_speed, na.rm = TRUE), avgspin = mean(release_spin_rate, na.rm = TRUE), count = n()) %>%
arrange(pitch_name)
tb6avgs
Here we can see that from Bauer’s June 6th game, the pitches with the highest speed were the fastball, sinker, and changeup. And his pitches with the highest spin rates were the knuckle curveball, slider, cutter, sinker, and fastball, all significantly above league average of 2280 rpm.
Bauer’s most utilized pitches during this game:
- Fastball (high velocity & high spin rate)
- Cutter (medium velocity & high spin rate)
- Slider (low velocity & high spin rate)
note: Bauer’s ERA during from this game was 2.40 Baseball Reference
tb6gr <- ## depicting Bauer's spin rates by pitch from June 6th
tbju6%>%
ggplot(aes(x = release_speed , y = release_spin_rate, color = pitch_name)) +
geom_point(stat = 'identity')+
xlab('Release Speed (mph)') +
ylab('Release Spin Rate (rpm)') +
labs(title = "Trevor Bauer's Spin Rate by Pitch Type",
color = 'Pitch Name',
caption = 'From game pitched on June 6th')
tb6gr

tb28gr <- ## depicting Bauer's spin rates by pitch from June 28th
tbju28%>%
ggplot(aes(x = release_speed , y = release_spin_rate, color = pitch_name)) +
geom_point(stat = 'identity')+
xlab('Release Speed (mph)') +
ylab('Release Spin Rate (rpm)') +
labs(title = "Trevor Bauer's Spin Rate by Pitch Type",
color = 'Pitch Name',
caption = 'From his last game on June 28th')
tb28gr

Here we can see the drastic drop in Bauer’s spin rate between the two games only 22 days apart. During Bauer’s June 6th game, before the League started implementing the 10-day suspension rule, it can be seen that he has several pitches being thrown at above 3000 rpm and with the exception of his changeup’s all of his pitches are rotating above 2500 rpm. Yet, by June 28th, Bauer didn’t have a single pitch with a spin rate above 3000 rpm. In addition to this, Bauer’s ERA during the two games increased from 2.40 to 2.59, meaning he was allowing significantly more runs and hits per inning after implementation. When seeing such large drops in spin rates, it can be speculated that the pitcher was utilizing sticky substances.
Bauer’s Sticky Verdict: GUILTY
Gerrit Cole
Yankee’s pitcher Gerrit Cole has been leading the league in strikeouts for the entire season. And after this infamous post game interview of Gerrit Cole, I can’t not look at his stats and see if the stuttering was an admission of guilt or if he was just tired.
gcoledt <-
read.csv('Gerrit Cole advanced stats.csv')
gcoledt
gccounts <-
gcoledt %>%
group_by(pitch_name) %>%
summarise(count = n())
gccounts
From this we can see that Cole’s most utilized pitch by far is his fastball, followed by his slider, knuckle curve, and changeup. Whereas his sinker is rarely used, only making an appearance 8 times in almost 800 pitches tracked.
gcju3 <- ## data from Cole's June 3rd game
gcoledt %>%
filter(game_date == '2021-06-03')
gcju3
ju3avg <-
gcju3%>%
select(pitch_name, release_spin_rate, release_speed) %>%
group_by(pitch_name) %>%
summarise(avgspeed = mean(release_speed, na.rm = TRUE), avgspin = mean(release_spin_rate, na.rm = TRUE), count = n()) %>%
arrange(pitch_name)
ju3avg
We can see that from Cole’s June 3rd game, the pitches with the highest speed were the fastball, sinker, changeup, and slider. And his pitches with the highest spin rates were the knuckle curve, slider, fastball, and sinker, with all being at least 100 rpm above the league average of 2280 rpm.
Cole’s most utilized pitches during this game:
Fastball (high velocity & high spin rate)
Knuckle Curve (medium velocity & high spin rate)
Changeup (high velocity & low spin rate)
note: Cole’s ERA during from this game was 2.26 Baseball Reference
gcjl17 <-
gcoledt %>%
filter(game_date == '2021-07-17')
gcjl17
jl17avg <-
gcjl17 %>%
group_by(pitch_name) %>%
select(pitch_name, release_spin_rate, release_speed) %>%
summarise(avgspin = mean(release_spin_rate, na.rm = TRUE), avgspeed = mean(release_speed, na.rm = TRUE), count = n()) %>%
arrange(pitch_name)
jl17avg
Here we can see that from Cole’s July 17th game, the pitches with the highest speed were the fastball, changeup, and slider. And his pitches with the highest spin rates were the knuckle curve, slider, and fastball, all still well above the league average of 2280 rpm.
Cole’s most utilized pitches during this game:
- Fastball (high velocity & medium spin rate)
- Knuckle Curve (medium velocity & high spin rate)
- Slider (medium velocity & high spin rate)
note: Cole’s ERA during from this game was 2.63 Baseball Reference
gcju3gr <-
gcju3 %>%
ggplot(aes(x = release_speed, y = release_spin_rate, color = pitch_name)) +
geom_point(stat = 'identity') +
xlab('Release Speed (mph)') +
ylab('Release Spin Rate (rpm)') +
labs(title = "Gerrit Cole's Spin Rate by Pitch",
caption = 'From the game pitched on June 3rd',
color = 'Pitch Type')+
scale_color_manual(values = c('4-Seam Fastball' = 'chocolate1',
'Changeup' = 'darkgoldenrod1',
'Knuckle Curve' = 'darkseagreen3',
'Sinker' = 'darkorchid1',
'Slider' = 'deepskyblue'))
gcju3gr

gcjl17gr <-
gcjl17 %>%
ggplot(aes(x = release_speed, y = release_spin_rate, color = pitch_name)) +
geom_point(stat = 'identity') +
xlab('Release Speed (mph)') +
ylab('Release Spin Rate (rpm)') +
labs(title = "Gerrit Cole's Spin Rate by Pitch Type",
caption = 'From the game Cole pitched on July 17th',
color = 'Pitch Type') +
scale_color_manual(values = c('4-Seam Fastball' = 'chocolate1',
'Changeup' = 'darkgoldenrod1',
'Knuckle Curve' = 'darkseagreen3',
'Slider' = 'deepskyblue'))
gcjl17gr

When comparing the two graphs the change in Cole’s spin rates isn’t as drastic as Bauer’s. His changeup, fastball, and slider remained relatively similar to what they were during his starts from his games prior to implementation. Additionally, the spin on his curveball increased, nearly reaching 3000 rpm during at bat number 40. His average release velocities also stayed relatively similar. Although his ERA did go up by 0.4 between these two games, which is a high increase to incur within a month and a half.
Cole’s Sticky Verdict: uh well… (probably) NOT GUILTY
Jacob deGrom
Jacob deGrom is arguably one of the best pitchers in all of baseball. With two Cy Young awards, a season ERA of 1.08, a season WAR of 5.0 (as of July 29th, 2021), and considering he was a shortstop in college, there is no doubt that he is a gifted player. Following all of his stellar performances this season, I was wondering if he had any change in pitching output.
dgstats <-
read.csv('deGrom Advanced Stats.csv')
dgstats
l8r <-
dgstats %>%
group_by(pitch_name) %>%
summarise(count = n())
l8r
stpg <-
dgstats %>%
select(game_date, release_spin_rate, pitch_name) %>%
group_by(game_date, pitch_name) %>%
summarise(avgspin = mean(release_spin_rate), pitch_name, game_date)%>%
#group_by(pitch_name, game_date) %>%
summarise(avgspin, pitch_name, game_date) %>%
mutate(date = date(game_date)) %>%
filter(pitch_name != ('Curveball')) %>%
filter(pitch_name != ('Changeup'))
`summarise()` has grouped output by 'game_date', 'pitch_name'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'game_date', 'pitch_name'. You can override using the `.groups` argument.
stpg
np <- stpg[!duplicated(stpg),]
np
idkyet <-
np %>%
ggplot(aes(fill = fct_rev(pitch_name), y = avgspin, x = date)) +
geom_bar(position = 'stack', stat = 'identity') +
xlab('Game Date') +
ylab('Average Spin Rate by Pitch')
idkyet

Garrett Richards
Garrett Richards’, Boston’s newest pitcher has had a very [word] season so far…
grichdt <- ## Garrett Richards data from Baseball Savant
read.csv('Garrett Richards advanced stats.csv')
grichdt
grcounts <-
grichdt %>%
group_by(pitch_name) %>%
summarise(count = n())
grcounts
Here we can see that Richards’ most utilized pitch is his fastball with over 900 appearances within between May 8th and July 9th, followed by his slider and curveball. Whereas he rarely threw changeup and sinkers, only being used 33 and 6 times respectively.
grjul9 <- ## filtering the data from Garrett Richard's most recent game
grichdt %>%
filter(game_date == '2021-07-09')
grjul9
jul9avgs <- ##averages from July 9th game
grjul9%>%
select(pitch_name, release_spin_rate, release_speed) %>%
group_by(pitch_name) %>%
summarise(avgspeed = mean(release_speed, na.rm = TRUE), avgspin = mean(release_spin_rate, na.rm = TRUE), count = n())
jul9avgs
Here we can see that from Richards’ July 9th game, the pitches with the highest speeds were the fastball and changeup. And his pitches with the highest spin rates were the curveball, slider, and fastball, all above the league average of 2280 rpm.
Richards’ most utilized pitches during this game:
Fastball (high velocity & medium spin rate)
Curveball (low velocity & high spin rate)
Slider (medium velocity & high spin rate)
note: Richards’ ERA during from this game was 4.91 Baseball Reference
grmay8 <- ## filtering the data from Richard's May 8th game
grichdt %>%
filter(game_date == '2021-05-08')
grmay8
may8avgs <-
grmay8%>%
select(release_spin_rate, release_speed, pitch_name) %>%
group_by(pitch_name) %>%
summarise(avgspeed = mean(release_speed, na.rm = TRUE), avgspin = mean(release_spin_rate, na.rm = TRUE), count = n())
may8avgs
During Richards’ May 8th game, it can seen he only utilized three different types of pitches. The two with the highest speeds were the fastball and slider. The two pitch types with the highest spin rates were the curveball and slider. Note all of his average spin rates from this game which were significantly above the league average of 2280 rpm.
Richards’ most utilized pitches during this game:
Fastball (high velocity & high spin rate)
Slider (medium velocity & high spin rate)
Curveball (low velocity & high spin rate)
note: Richards’ ERA during from this game was 4.54 Baseball Reference
my8gr <-
grmay8%>%
ggplot(aes(x = release_speed, y = release_spin_rate, color = pitch_name))+
geom_point() +
xlab('Release Speed (mph)')+
ylab('Spin Rate (rpm)') +
labs(title = 'Gerritt Richards Spin Rate by Pitch',
color = 'Pitch Type',
caption = 'From game pitched on May 8th') +
scale_color_manual(values = c('4-Seam Fastball' = 'chocolate1',
'Curveball' = 'cyan3',
'Slider' = 'darkorchid2'))
my8gr

grjul9gr <-
grjul9 %>%
ggplot(aes(x = release_speed, y = release_spin_rate, color = pitch_name)) +
geom_point() +
xlab('Release Speed (mph)') +
ylab('Release Spin Rate') +
labs(title = 'Gerritt Richards Spin Rate by Pitch',
caption = 'For game pitched on July 9th',
color = 'Pitch Type') +
scale_color_manual(values = c('4-Seam Fastball' = 'chocolate1',
'Changeup' = 'chartreuse3',
'Curveball' = 'cyan3',
'Slider' = 'darkorchid2'))
grjul9gr

When examining Richards’ pitch velocities and spin rates between these two games there is a clear difference in performance. Generally, his pitches are more concentrated in the July game, showing that there’s more consistency between the pitches he was throwing in July than in May. Richards’ went from having more than half of his curveballs above 3300 rpm in May to not even having a single curveball reach 3000 rpm. When comparing the averages there’s been a drop of 410 rpm in this pitch and a 4.25 mph drop in velocity. When looking at his sliders, the spin rates are concentrated around 2900 rpm, which then dropped to around 2600 rpm. The velocity change with this pitch wasn’t as drastic shifting with an average of about 1.9 mph, which wouldn’t be very suspicious if not for the other changes. Additionally, when looking at his fastballs (his most utilized pitch) there isn’t as significant of a change. The velocities are concentrated in the same area and only had a change in 0.45 mph. The average spin rates for the fastball only dropped by 175 rpm, which by itself isn’t particularly suspicious. Yet when looking at all of the changes in Richards’ pitches and his game specific ERA increasing by 0.63 there is more than ample evidence that Richards’ was in fact utilizing sticky substances.
Richards’ Sticky Verdict: GUILTY
LS0tCmF1dGhvcjogTW9qaXNvbHV3YSAoSmlzbykgQXdlCnRpdGxlOiAiT3BlcmF0aW9uIFN0aWNreSBHYXRlIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIFdoYXQgaXMgT3BlcmF0aW9uIFN0aWNreSBHYXRlPwoKTWFqb3IgTGVhZ3VlIEJhc2ViYWxsJ3MgMjAyMSBzZWFzb24gaGFzIGJlZW4gbWFya2VkIGJ5IHJlY29yZCBicmVha2luZyBzdGF0aXN0aWNzLiBQYXJ0aWN1bGFybHkgdGhlIHJlY29yZCBsb3cgRVJBJ3MsIGV4dHJlbWVseSBoaWdoIHNwaW4gcmF0ZXMsIGFuZCBhIHJlY29yZGluZyBicmVha2luZyBhbW91bnQgb2Ygbm8taGl0dGVycyBhIGZldyBtb250aHMgaW50byB0aGUgc2Vhc29uLiBNYW55IGNvbnNpZGVyIGJhc2ViYWxsIGJvcmluZyBkdWUgdG8gYSAnbGFjayBvZiBhY3Rpb24nLCB3ZWxsIHRoaXMgc2Vhc29uIHRoYXQncyBwcm92aW5nIHRydWUuIAotYXZnIHNwaW4gcmF0ZSBwcmlvciB0byBKdW5lIDFzdCB3YXMgYXJvdW5kIDIyODAKLW1lbnRpb24gdGhlIG9nIHN0ZXJvaWQgZXJhCi1kYXRhIGZyb20gc3RhcnQgb2Ygc2Vhc29uIHRvIEp1bmUgMSwgYW5kIEp1bmUgMSB0byBKdWx5IDE3LCBmcm9tIEJhc2ViYWxsIFNhdmFudC4KLXNpbmtlcnMgYW5kIGN1cnZlYmFsbHMKCiMgQmVmb3JlIHRoZSBDcmFja2Rvd24KCkZvciBhIGxvbmcgdGltZSBNTEIgdGVhbXMgaGFkIHdoYXQgc29tZSB3b3VsZCBjYWxsIGEgZ2VudGxlbWFuJ3MgYWdyZWVtZW50IG92ZXIgdXRpbGl6aW5nIGZvcmVpZ24gc3Vic3RhbmNlcy4gSW5pdGlhbGx5IHRoaXMgc3RhcnRlZCBhcyBhIHdheSBmb3IgcGl0Y2hlcnMgdG8gYmV0dGVyIHRoZWlyIGdyaXAgb24gdGhlIGJhbGwgd2hlbiB0aGV5IHBpdGNoZWQuIE5vdywgaXQncyBnb3R0ZW4gdG8gdGhlIHBvaW50IHRoYXQgdGhlIGZvcmVpZ24gc3Vic3RhbmNlcyBhcmUgc28gc3RpY2t5IHRoYXQgcmF0aGVyIHRoYW4ganVzdCBoZWxwaW5nIHBpdGNoZXJzIGdyaXAgdGhlIGJhbGwsIGl0J3MgbWFraW5nIHRoZSBiYWxsIHN0aWNrIHRvIHRoZWlyIGhhbmQgZm9yIGxvbmdlciwgdGh1cyBpbmNyZWFzaW5nIHRoZSBzcGluIHJhdGUgb2YgdGhlIGJhbGwgYW5kIG1ha2luZyBpdCBoYXJkZXIgdG8gaGl0LiBBcyB0aGUgc3BpbiBvZiB0aGUgYmFsbCBpbmNyZWFzZXMgdGhlIGdlbmVyYWwgbG9jYXRpb24gaW4gd2hpY2ggdGhlIGJhbGwgaXMgZ2V0dGluZyB0aHJvd24gaXMgaGlnaGVyLCBhZGRpbmcgdG8gdGhlIGRpZmZpY3VsdGllcyBoaXR0ZXJzIGFyZSBhbHJlYWR5IGZhY2luZy4gVGhlIHNwaW4gb24gcGl0Y2hlcyBsaWtlIHRoZSA0LXNlYW0gZmFzdGJhbGxzIGlzIGEgYmFjayBzcGluLCB3aGljaCBvcHBvc2VzIHRoZSBkb3dud2FyZCBmb3JjZSBvZiBncmF2aXR5IG9uIHRoZSBiYWxsICh0aGluayBvZiB0aGUgdGVybSAncmlzaW5nIGZhc3RiYWxsJykuIAoKVGhlIE1MQiBtYWRlIGEgZGVjaXNpb24gY29taW5nIG91dCBhZ2FpbnN0IGZvcmVpZ24gc3Vic3RhbmNlcyBieSBzdGF0aW5nIHRoYXQgc3RhcnRpbmcgb24gSnVuZSAxc3QgdW1waXJlcyB3aWxsIGJlZ2luIGNoZWNraW5nIGZvciBwaXRjaGVycyB1c2luZyBmb3JlaWduIHN1YnN0YW5jZXMgYW5kIG9uIEp1bmUgMTZ0aCBhbm5vdW5jZWQgcGxheWVycyBjYXVnaHQgdXNpbmcgdGhlbSB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZ2FtZSwgcGxhY2VkIG9uIGEgMTAgZ2FtZSBzdXNwZW5zaW9uLCBhbmQgZmluZWQuIE1hbnkgcGVvcGxlIGhhdmUgYXJndWVkIHRoYXQgdGhlc2Ugc3RhdGVtZW50cyB3b24ndCBkZXRlciBwaXRjaGVycyBmcm9tIHV0aWxpemluZyBmb3JlaWduIHN1YnN0YW5jZXMuIFlldCBtYW55IGFuYWx5c3RzIGhhdmUgYmVlbiBzYXlpbmcgc3BpbiByYXRlcyBnb2luZyBkb3duIGFuZCBiYXR0aW5nICBhdmVyYWdlcyBnb2luZyB1cC4gSW4gdGhpcyBub3RlYm9vayB3ZSB3aWxsIGJlIGV4YW1pbmluZyB0aGUgYWZmZWN0IG9mIHRoZSBNTEIncyBuZXcgaW1wbGVtZW50YXRpb24gYW5kIGV4YW1pbmluZyBjaGFuZ2VzIHdpdGggaW5kaXZpZHVhbCBwbGF5ZXJzLgoKQWxsIHRoZSBkYXRhIGluY2x1ZGVkIGhhcyBiZWVuIHByb3ZpZGVkIGJ5IEJhc2ViYWxsIFNhdmFudCBmb3VuZCB0aHJvdWdoIHV0aWxpemluZyB0aGUgc2VhcmNoIGZlYXR1cmUgYW5kIEJhc2ViYWxsIFJlZmVyZW5jZSAobGlua2VkIHdoZW4gcmVmZXJlbmNlZCkuCgoKCiMjIFZlbG9jaXR5IHZzIFNwaW4gUmF0ZQoKSXQncyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IGdlbmVyYWxseSBhcyBpbmNyZWFzZXMgdmVsb2NpdHkgc28gZG9lcyBzcGluIHJhdGUuIEluIHRoaXMgc2VjdGlvbiB3ZSB3aWxsIGJlIGNvbXBhcmluZyBwaXRjaGVycyBzcGluIHJhdGVzIHZzIHZlbG9jaXRpZXMgYmVmb3JlIGFuZCBhZnRlciBKdW5lIDFzdC4KCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKSAjIyBsb2FkaW5nIHBhY2thZ2VzCmxpYnJhcnkoZ2dFeHRyYSkKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobHVicmlkYXRlKQpgYGAKCgoKYGBge3J9CmI0IDwtCiAgcmVhZC5jc3YoJ2I0SnVuZTEuY3N2JykKYjQKYGBgCgoKIApgYGB7cn0KYWZ0IDwtCiAgcmVhZC5jc3YoJ2FmdEp1bmUxc3QuY3N2JykKYWZ0CmBgYAoKCmBgYHtyfQpiNGdyIDwtCiAgYjQgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdmVsb2NpdHksIHkgPSBzcGluX3JhdGUsIGNvbG9yID0gdG90YWxfcGl0Y2hlcykpICsKICBnZW9tX3BvaW50KHN0YXQgPSAnaWRlbnRpdHknKSArCiAgeGxhYignVmVsb2NpdHkgKG1waCknKSArCiAgeWxhYignU3BpbiBSYXRlIChycG0pJykgKwogIGdndGl0bGUoJ1NwaW4gUmF0ZSBWUyBWZWxvY2l0eSBQcmlvciB0byBKdW5lIDFzdCcpICsKICBsYWJzKGNvbG9yID0gJ1RvdGFsIFBpdGNoZXMnKQoKIyN1c2luZyBnZ0V4dHJhIHBhY2thZ2UgdG8gYWRkIGhpc3RvZ3JhbXMgdG8gc2hvdyB0aGUgZGlzdHJpYnV0aW9uIG9mIGRhdGEgd2l0aGluIHRoZSBzY2F0dGVycGxvdApwMSA8LQogIGdnTWFyZ2luYWwoYjRnciwgdHlwZSA9ICdoaXN0b2dyYW0nKQpwMQoKCmFmdGdyIDwtCiAgYWZ0ICU+JQogIGdncGxvdChhZXMoeCA9IHZlbG9jaXR5LCB5ID0gc3Bpbl9yYXRlLCBjb2xvciA9IHRvdGFsX3BpdGNoZXMpKSArCiAgZ2VvbV9wb2ludChzdGF0ID0gJ2lkZW50aXR5JykgKwogIHhsYWIoJ1ZlbG9jaXR5IChtcGgpJykgKwogIHlsYWIoJ1NwaW4gUmF0ZSAocnBtKScpICsKICBnZ3RpdGxlKCdTcGluIFJhdGUgVlMgVmVsb2NpdHkgQWZ0ZXIgSnVuZSAxc3QnKSArCiAgbGFicyhjb2xvciA9ICdUb3RhbCBQaXRjaGVzJykKCnAyIDwtICAKICBnZ01hcmdpbmFsKGFmdGdyLCB0eXBlID0gJ2hpc3RvZ3JhbScpCnAyCmBgYAoKCgpUaGUgZ3JhcGggb2YgdGhlIGRhdGEgYmVmb3JlIEp1bmUgMXN0IHNob3dzIHRoYXQgZ2VuZXJhbGx5IHBpdGNoZXJzIGF2ZXJhZ2Ugc3BpbiByYXRlcyBhcmUgY29uY2VudHJhdGVkIGJldHdlZW4gMjIwMCBycG0gYW5kIDI2MDAgcnBtIGFuZCB0aGUgdmVsb2NpdGllcyByYW5nZSBmcm9tIHRoZSB1cHBlciA4MHMgdG8gbWlkIDkwcy4gCgpUaGUgZ3JhcGggb2YgdGhlIGRhdGEgZm9sbG93aW5nIEp1bmUgMXN0LCBkaXNwbGF5cyBhIGhpZ2hlciBjb25nbG9tZXJhdGlvbiBvZiBwaXRjaGVycyB3aXRoIGF2ZXJhZ2UgcGl0Y2hlcyBiZXR3ZWVuIDIwMDAgYW5kIDI1MDAgcnBtIGFuZCBsZXNzIG91dGxpZXJzIHdpdGggc3BpbiByYXRlcyBhYm92ZSAyNzUwIHJwbS4gV2l0aCB2ZWxvY2l0aWVzIGNvbmNlbnRyYXRlZCBiZXR3ZWVuIHRoZSB1cHBlciA4MCdzIGFuZCBsb3dlciA5MCdzIGFuZCBzcGluIHJhdGVzIGJldHdlZW4gMjAwMCBycG0gYW5kIDI1MDAgcnBtLgoKVXBvbiBmdXJ0aGVyIGluc3BlY3Rpb24gb2YgdGhlIHNjYXR0ZXJwbG90IGl0IGFwcGVhcnMgdGhhdCBtb3N0IG9mIHRoZSBvdXRsaWVycyBhcmUgZGFya2VyIHNoYWRlZCBkb3RzIHJlcHJlc2VudGluZyBwaXRjaGVyIHdobyd2ZSB0aHJvd24gYmV0d2VlbiAxIGFuZCAyNTAgcGl0Y2hlcy4gQmVjYXVzZSB0aGlzIGRhdGEgaXMgYmFzZWQgb24gYXZlcmFnZXMgYW5kIHNtYWxsZXIgc2FtcGxlIHNpemVzIGFyZSBnZW5lcmFsbHkgbGVzcyByZXByZXNlbnRhdGl2ZSBvZiB0aGUgaW5kaXZpZHVhbC4gVGhpcyBwcm9tcHRlZCBtZSB0byBzZWUgaWYgdGhlcmUgd2FzIGEgZGlmZmVyZW5jZSB3aGVuIGlmIEkgaW5jcmVhc2VkIHRoZSBtaW5pbXVtIG51bWJlciBvZiBwaXRjaGVzIHRvIGF0IGxlYXN0IDI1MC4KCgpgYGB7cn0KYjRhYnYgPC0KICBiNCU+JQogIGZpbHRlcih0b3RhbF9waXRjaGVzID4gMjQ5KQpiNGFidgpgYGAKCmBgYHtyfQphZnRhYnYgPC0KICBhZnQlPiUKICBmaWx0ZXIodG90YWxfcGl0Y2hlcyA+IDI0OSkKYWZ0YWJ2CmBgYAoKCgoKYGBge3J9CmJhYnZnciA8LQogIGI0YWJ2ICU+JQogIGdncGxvdChhZXMoeCA9IHZlbG9jaXR5LCB5ID0gc3Bpbl9yYXRlLCBjb2xvciA9IHRvdGFsX3BpdGNoZXMpKSArCiAgZ2VvbV9wb2ludChzdGF0ID0gJ2lkZW50aXR5JykgKwogIHhsYWIoJ1ZlbG9jaXR5IChtcGgpJykgKwogIHlsYWIoJ1NwaW4gUmF0ZSAocnBtKScpICsKICBsYWJzKGNvbG9yID0gJ1RvdGFsIFBpdGNoZXMnLAogICAgICAgdGl0bGUgPSAnU3BpbiBSYXRlIHZzIFZlbG9jaXR5IEJlZm9yZSBKdW5lIDFzdCcsCiAgICAgICBjYXB0aW9uID0gJ0ZvciBwaXRjaGVycyB3aXRoIG92ZXIgMjUwIHBpdGNoZXMnKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19jKCkKZzEgPC0KICBnZ01hcmdpbmFsKGJhYnZnciwgdHlwZSA9ICdoaXN0b2dyYW0nKQpnMQoKCmFmYWJ2Z3IgPC0KICBhZnRhYnYgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdmVsb2NpdHksIHkgPSBzcGluX3JhdGUsIGNvbG9yID0gdG90YWxfcGl0Y2hlcykpICsKICBnZW9tX3BvaW50KHN0YXQgPSAnaWRlbnRpdHknKSArCiAgeGxhYignVmVsb2NpdHkgKG1waCknKSArCiAgeWxhYignU3BpbiBSYXRlIChycG0pJykgKwogIGxhYnMoY29sb3IgPSAnVG90YWwgUGl0Y2hlcycsCiAgICAgICB0aXRsZSA9ICdTcGluIFJhdGUgdnMgVmVsb2NpdHkgQWZ0ZXIgSnVuZSAxc3QnLAogICAgICAgY2FwdGlvbiA9ICdGb3IgcGl0Y2hlcnMgd2l0aCBvdmVyIDI1MCBwaXRjaGVzJykgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYygpCgprMSA8LSAKICBnZ01hcmdpbmFsKGFmYWJ2Z3IsIHR5cGUgPSAnaGlzdG9ncmFtJykKazEKYGBgCgpIZXJlIHdlIGNhbiBzZWUgYSBtb3JlIG5vdGFibGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGF2ZXJhZ2Ugc3BpbiByYXRlcyBhbmQgdmVsb2NpdGllcy4gUHJpb3IgdG8gSnVuZSAxc3Qgd2UgY2FuIHNlZSB0aGF0IGF2ZXJhZ2UgdmVsb2NpdGllcyB3ZXJlIGdlbmVyYWxseSBiZXR3ZWVuIHRoZSB1cHBlciA4MHMgYW5kIG1pZCA5MHMsIHdpdGggc3BpbiByYXRlcyByYW5naW5nIGJldHdlZW4gMjEwMCBhbmQgMjYwMCBycG0uIFRoZSBleHRyZW1lcyBpbmNsdWRlZCA1IHBpdGNoZXJzIHdpdGggc3BpbiByYXRlcyBhYm92ZSAyNzUwIHJwbSBhbmQgMjAgcGl0Y2hlcnMgYWJvdmUgOTUgbXBoLiAKSW4gY29udHJhc3Qgd2UgY2FuIHNlZSB0aGF0IGFmdGVyIEp1bmUgMXN0LCB2ZWxvY2l0aWVzIGFyZSBjb25jZW50cmF0ZWQgYmV0d2VlbiB0aGUgbWlkIDgwcyB0byBsb3dlciA5MCdzIGFuZCBzcGluIHJhdGVzIGJldHdlZW4gMjAwMCBhbmQgMjUwMCBycG0uIFRoZSBleHRyZW1lcyBoZXJlIG5vdyBvbmx5IGluY2x1ZGUgMSBwaXRjaGVyIHdpdGggYW4gYXZlcmFnZSBzcGluIHJhdGUgYWJvdmUgMjc1MCBhbmQgMyBwaXRjaGVycyBhYm92ZSA5NSBtcGguIEFkZGl0aW9uYWxseSB0aGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBvZiB0aGUgdmVsb2NpdGllcyBjaGFuZ2VkIGZyb20gbGVmdCBza2V3IHRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gV2hlcmVhcyB0aGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBvZiB0aGUgc3BpbiByYXRlcyB3ZW50IGZyb20gYmktbW9kYWwgdG8gYSBub3JtYWwgZGlzdHJpYnV0aW9uIGZvbGxvd2luZyBKdW5lIDFzdC4KCgojIEluZGl2aWR1YWwgUGl0Y2hlciBDaGFuZ2VzCgpJbiB0aGlzIHNlY3Rpb24gd2Ugd2lsbCBiZSBleGFtaW5pbmcgYSBjaGFuZ2UgaW4gc3BpbiByYXRlLCB2ZWxvY2l0eSwgYW5kIG92ZXJhbGwgcGVyZm9ybWFuY2UgKGlmIGFueSkgYmV0d2VlbiBzcGVjaWZpYyBwaXRjaGVyczogVHJldm9yIEJhdWVyLCBHZXJyaXQgQ29sZSwgSmFjb2IgZGVHcm9tLCBhbmQgR2FycmV0dCBSaWNoYXJkcy4KCiMjIFRyZXZvciBCYXVlcgoKSXQncyBoYXJkIHRvIGhhdmUgYW55IGNvbnZlcnNhdGlvbiBhYm91dCBmb3JlaWduIHN1YnN0YW5jZXMgaW4gYmFzZWJhbGwgd2l0aG91dCBtZW50aW9uaW5nIFRyZXZvciBCYXVlci4gRnJvbSBiZWluZyBzb21lb25lIHdobyBpbml0aWFsbHkgc3Bva2VuIGFnYWluc3QgZm9yZWlnbiBzdWJzdGFuY2VzIGFuZCBvbmNlIGV2ZW4gc3RhdGluZyB0aGF0IHRoZXkgY291bGQgYmUgbW9yZSBwb3dlcmZ1bCB0aGFuIHN0ZXJvaWRzLCB0byBub3cgYmVpbmcgYWNjdXNlZCBvZiBoYXZpbmcgdGhlIG1vc3QgZWZmZWN0aXZlIHN0aWNreSBzdWJzdGFuY2UgY29tYmluYXRpb24gaW4gdGhlIGxlYWd1ZSwgQmF1ZXIncyBuYW1lIGhhcyBiZWVuIGJyb3VnaHQgdXAgYSBsb3QuIENvbnNpZGVyaW5nIHJlY2VudCBldmVudHMgcmVnYXJkaW5nIEJhdWVyJ3MgYXJyZXN0IGFuZCBhbGxlZ2F0aW9uLCB0aGUgZGF0YSBhdmFpbGFibGUgaXMgbW9yZSBsaW1pdGVkIHRoYW4gd2l0aCBvdGhlciBwbGF5ZXJzLgoKYGBge3J9CmJhdWVyIDwtICMjIGRvd25sb2FkZWQgZnJvbSBCYXNlYmFsbCBTYXZhbnQKICByZWFkLmNzdignYmF1ZXIgYWR2YW5jZWQgc3RhdHMuY3N2JykKYmF1ZXIKYGBgCgoKYGBge3J9Cm51bSA8LSAgIyMgZmluZGluZyBjb3VudHMgb2YgZWFjaCBwaXRjaCB0eXBlCiAgYmF1ZXIgJT4lCiAgZ3JvdXBfYnkocGl0Y2hfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKQpudW0KYGBgCgoKRnJvbSB0aGlzIGRhdGEgd2UgY2FuIHNlZSB0aGF0IGR1cmluZyB0aGUgbW9udGggb2YgSnVuZSwgQmF1ZXIncyBtb3N0IHV0aWxpemVkIHBpdGNoZXMgd2VyZSB0aGUgZmFzdGJhbGwsIGN1dHRlciwgYW5kIHNsaWRlci4KCgojIyMjIEp1bmUgMjh0aAoKYGBge3J9CnRianUyOCA8LQogIGJhdWVyICU+JQogIGZpbHRlcihnYW1lX2RhdGUgPT0gJzIwMjEtMDYtMjgnKQp0Ymp1MjgKYGBgCgpgYGB7cn0KdGIyYXZncyA8LSAjIyBmaW5kaW5nIGdhbWUgYXZlcmFnZXMgZnJvbSB0aGUgSnVuZSAyOHRoIGdhbWUKICB0Ymp1MjggJT4lCiAgc2VsZWN0KHBpdGNoX25hbWUsIHJlbGVhc2Vfc3BlZWQsIHJlbGVhc2Vfc3Bpbl9yYXRlKSAlPiUKICBncm91cF9ieShwaXRjaF9uYW1lKSAlPiUKICBzdW1tYXJpc2UoYXZnc3BlZWQgPSBtZWFuKHJlbGVhc2Vfc3BlZWQsIG5hLnJtID0gVFJVRSksIGF2Z3NwaW4gPSBtZWFuKHJlbGVhc2Vfc3Bpbl9yYXRlLCBuYS5ybSA9IFRSVUUpLCBjb3VudCA9IG4oKSkgJT4lCiAgYXJyYW5nZShwaXRjaF9uYW1lKQp0YjJhdmdzCmBgYAoKCgpGcm9tIHRoaXMgd2UgY2FuIHNlZSB0aGF0IEJhdWVyJ3MgZmFzdGVzdCBhdmVyYWdlIHBpdGNoZXMgYXJlIGhpcyBzaW5rZXIsIGZhc3RiYWxsLCBhbmQgY2hhbmdldXAuIEhpcyBwaXRjaGVzIHdpdGggdGhlIGhpZ2hlc3Qgc3BpbiByYXRlcyBhcmUgdGhlIGtudWNrbGUgY3VydmUsIHNsaWRlciwgY3V0dGVyLCBhbmQgZmFzdGJhbGwsIGFsbCB3aXRoIHNwaW4gcmF0ZXMgYWxsIHdlbGwgYWJvdmUgdGhlIGF2ZXJhZ2Ugc3BpbiByYXRlIG9mIDIyODAgcnBtLgoKQmF1ZXIncyBtb3N0IHV0aWxpemVkIHBpdGNoZXMgdGhpcyBnYW1lOgoKKiBDdXR0ZXIgKG1lZGl1bSB2ZWxvY2l0eSAmIGhpZ2ggc3BpbiByYXRlKQoKKiBTbGlkZXIgKGxvdyB2ZWxvY2l0eSAmIGhpZ2ggc3BpbiByYXRlKQoKKiBGYXN0YmFsbCAoaGlnaCB2ZWxvY2l0eSAmIHNwaW4gcmF0ZSkKCgpub3RlOiBCYXVlcidzIEVSQSBkdXJpbmcgdGhpcyBnYW1lIHdhcyAyLjU5IFtCYXNlYmFsbCBSZWZlcmVuY2VdKGh0dHBzOi8vd3d3LmJhc2ViYWxsLXJlZmVyZW5jZS5jb20vYm94ZXMvTEFOL0xBTjIwMjEwNjI4MC5zaHRtbCkKCiMjIyMgSnVuZSA2dGgKCmBgYHtyfQp0Ymp1NiA8LQogIGJhdWVyICU+JQogIGZpbHRlcihnYW1lX2RhdGUgPT0gJzIwMjEtMDYtMDYnKQp0Ymp1NgpgYGAKCgpgYGB7cn0KdGI2YXZncyA8LQogIHRianU2JT4lCiAgc2VsZWN0KHBpdGNoX25hbWUsIHJlbGVhc2Vfc3BlZWQsIHJlbGVhc2Vfc3Bpbl9yYXRlKSAlPiUKICBncm91cF9ieShwaXRjaF9uYW1lKSAlPiUKICBzdW1tYXJpc2UoYXZnc3BlZWQgPSBtZWFuKHJlbGVhc2Vfc3BlZWQsIG5hLnJtID0gVFJVRSksIGF2Z3NwaW4gPSBtZWFuKHJlbGVhc2Vfc3Bpbl9yYXRlLCBuYS5ybSA9IFRSVUUpLCBjb3VudCA9IG4oKSkgJT4lCiAgYXJyYW5nZShwaXRjaF9uYW1lKQp0YjZhdmdzCmBgYAoKSGVyZSB3ZSBjYW4gc2VlIHRoYXQgZnJvbSBCYXVlcidzIEp1bmUgNnRoIGdhbWUsIHRoZSBwaXRjaGVzIHdpdGggdGhlIGhpZ2hlc3Qgc3BlZWQgd2VyZSB0aGUgZmFzdGJhbGwsIHNpbmtlciwgYW5kIGNoYW5nZXVwLiBBbmQgaGlzIHBpdGNoZXMgd2l0aCB0aGUgaGlnaGVzdCBzcGluIHJhdGVzIHdlcmUgdGhlIGtudWNrbGUgY3VydmViYWxsLCBzbGlkZXIsIGN1dHRlciwgc2lua2VyLCBhbmQgZmFzdGJhbGwsIGFsbCBzaWduaWZpY2FudGx5IGFib3ZlIGxlYWd1ZSBhdmVyYWdlIG9mIDIyODAgcnBtLgoKCkJhdWVyJ3MgbW9zdCB1dGlsaXplZCBwaXRjaGVzIGR1cmluZyB0aGlzIGdhbWU6CgoqIEZhc3RiYWxsIChoaWdoIHZlbG9jaXR5ICYgaGlnaCBzcGluIHJhdGUpCiogQ3V0dGVyIChtZWRpdW0gdmVsb2NpdHkgJiBoaWdoIHNwaW4gcmF0ZSkKKiBTbGlkZXIgKGxvdyB2ZWxvY2l0eSAmIGhpZ2ggc3BpbiByYXRlKQoKCm5vdGU6IEJhdWVyJ3MgRVJBIGR1cmluZyBmcm9tIHRoaXMgZ2FtZSB3YXMgMi40MCBbQmFzZWJhbGwgUmVmZXJlbmNlXShodHRwczovL3d3dy5iYXNlYmFsbC1yZWZlcmVuY2UuY29tL2JveGVzL0FUTC9BVEwyMDIxMDYwNjAuc2h0bWwpCgpgYGB7cn0KdGI2Z3IgPC0gICAgIyMgZGVwaWN0aW5nIEJhdWVyJ3Mgc3BpbiByYXRlcyBieSBwaXRjaCBmcm9tIEp1bmUgNnRoCiAgdGJqdTYlPiUKICBnZ3Bsb3QoYWVzKHggPSByZWxlYXNlX3NwZWVkICwgeSA9IHJlbGVhc2Vfc3Bpbl9yYXRlLCBjb2xvciA9IHBpdGNoX25hbWUpKSArCiAgZ2VvbV9wb2ludChzdGF0ID0gJ2lkZW50aXR5JykrCiAgeGxhYignUmVsZWFzZSBTcGVlZCAobXBoKScpICsKICB5bGFiKCdSZWxlYXNlIFNwaW4gUmF0ZSAocnBtKScpICsKICBsYWJzKHRpdGxlID0gIlRyZXZvciBCYXVlcidzIFNwaW4gUmF0ZSBieSBQaXRjaCBUeXBlIiwKICAgICAgIGNvbG9yID0gJ1BpdGNoIE5hbWUnLAogICAgICAgY2FwdGlvbiA9ICdGcm9tIGdhbWUgcGl0Y2hlZCBvbiBKdW5lIDZ0aCcpCnRiNmdyCgp0YjI4Z3IgPC0gICMjIGRlcGljdGluZyBCYXVlcidzIHNwaW4gcmF0ZXMgYnkgcGl0Y2ggZnJvbSBKdW5lIDI4dGgKICB0Ymp1MjglPiUKICBnZ3Bsb3QoYWVzKHggPSByZWxlYXNlX3NwZWVkICwgeSA9IHJlbGVhc2Vfc3Bpbl9yYXRlLCBjb2xvciA9IHBpdGNoX25hbWUpKSArCiAgZ2VvbV9wb2ludChzdGF0ID0gJ2lkZW50aXR5JykrCiAgeGxhYignUmVsZWFzZSBTcGVlZCAobXBoKScpICsKICB5bGFiKCdSZWxlYXNlIFNwaW4gUmF0ZSAocnBtKScpICsKICBsYWJzKHRpdGxlID0gIlRyZXZvciBCYXVlcidzIFNwaW4gUmF0ZSBieSBQaXRjaCBUeXBlIiwKICAgICAgIGNvbG9yID0gJ1BpdGNoIE5hbWUnLAogICAgICAgY2FwdGlvbiA9ICdGcm9tIGhpcyBsYXN0IGdhbWUgb24gSnVuZSAyOHRoJykKdGIyOGdyCmBgYAoKCkhlcmUgd2UgY2FuIHNlZSB0aGUgZHJhc3RpYyBkcm9wIGluIEJhdWVyJ3Mgc3BpbiByYXRlIGJldHdlZW4gdGhlIHR3byBnYW1lcyBvbmx5IDIyIGRheXMgYXBhcnQuIER1cmluZyBCYXVlcidzIEp1bmUgNnRoIGdhbWUsIGJlZm9yZSB0aGUgTGVhZ3VlIHN0YXJ0ZWQgaW1wbGVtZW50aW5nIHRoZSAxMC1kYXkgc3VzcGVuc2lvbiBydWxlLCBpdCBjYW4gYmUgc2VlbiB0aGF0IGhlIGhhcyBzZXZlcmFsIHBpdGNoZXMgYmVpbmcgdGhyb3duIGF0IGFib3ZlIDMwMDAgcnBtIGFuZCB3aXRoIHRoZSBleGNlcHRpb24gb2YgaGlzIGNoYW5nZXVwJ3MgYWxsIG9mIGhpcyBwaXRjaGVzIGFyZSByb3RhdGluZyBhYm92ZSAyNTAwIHJwbS4gWWV0LCBieSBKdW5lIDI4dGgsIEJhdWVyIGRpZG4ndCBoYXZlIGEgc2luZ2xlIHBpdGNoIHdpdGggYSBzcGluIHJhdGUgYWJvdmUgMzAwMCBycG0uIEluIGFkZGl0aW9uIHRvIHRoaXMsIEJhdWVyJ3MgW0VSQV0oaHR0cHM6Ly9naXRodWIuY29tL2ppc29hd2UvTUxCLURhdGEtVmlzdWFsaXphdGlvbnMvYmxvYi9tYWluL0VSQSUyMEV4cGxhaW5lZC5SbWQpIGR1cmluZyB0aGUgdHdvIGdhbWVzIGluY3JlYXNlZCBmcm9tIDIuNDAgdG8gMi41OSwgbWVhbmluZyBoZSB3YXMgYWxsb3dpbmcgc2lnbmlmaWNhbnRseSBtb3JlIHJ1bnMgYW5kIGhpdHMgcGVyIGlubmluZyBhZnRlciBpbXBsZW1lbnRhdGlvbi4gV2hlbiBzZWVpbmcgc3VjaCBsYXJnZSBkcm9wcyBpbiBzcGluIHJhdGVzLCBpdCBjYW4gYmUgc3BlY3VsYXRlZCB0aGF0IHRoZSBwaXRjaGVyIHdhcyB1dGlsaXppbmcgc3RpY2t5IHN1YnN0YW5jZXMuCgojIyMjIEJhdWVyJ3MgU3RpY2t5IFZlcmRpY3Q6IEdVSUxUWQoKCgojIyBHZXJyaXQgQ29sZQoKWWFua2VlJ3MgcGl0Y2hlciBHZXJyaXQgQ29sZSBoYXMgYmVlbiBsZWFkaW5nIHRoZSBsZWFndWUgaW4gc3RyaWtlb3V0cyBmb3IgdGhlIGVudGlyZSBzZWFzb24uIEFuZCBhZnRlciBbdGhpc10oaHR0cHM6Ly90d2l0dGVyLmNvbS9tcm9iZXJzb24yMi9zdGF0dXMvMTQwMjM3NzYxNDA4NjQ2NzU4Nj9zPTIwKSBpbmZhbW91cyBwb3N0IGdhbWUgaW50ZXJ2aWV3IG9mIEdlcnJpdCBDb2xlLCBJIGNhbid0IG5vdCBsb29rIGF0IGhpcyBzdGF0cyBhbmQgc2VlIGlmIHRoZSBzdHV0dGVyaW5nIHdhcyBhbiBhZG1pc3Npb24gb2YgZ3VpbHQgb3IgaWYgaGUgd2FzIGp1c3QgdGlyZWQuIAoKCmBgYHtyfQpnY29sZWR0IDwtCiAgcmVhZC5jc3YoJ0dlcnJpdCBDb2xlIGFkdmFuY2VkIHN0YXRzLmNzdicpCmdjb2xlZHQKYGBgCgpgYGB7cn0KZ2Njb3VudHMgPC0KICBnY29sZWR0ICU+JQogIGdyb3VwX2J5KHBpdGNoX25hbWUpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkKZ2Njb3VudHMKYGBgCgoKRnJvbSB0aGlzIHdlIGNhbiBzZWUgdGhhdCBDb2xlJ3MgbW9zdCB1dGlsaXplZCBwaXRjaCBieSBmYXIgaXMgaGlzIGZhc3RiYWxsLCBmb2xsb3dlZCBieSBoaXMgc2xpZGVyLCBrbnVja2xlIGN1cnZlLCBhbmQgY2hhbmdldXAuIFdoZXJlYXMgaGlzIHNpbmtlciBpcyByYXJlbHkgdXNlZCwgb25seSBtYWtpbmcgYW4gYXBwZWFyYW5jZSA4IHRpbWVzIGluIGFsbW9zdCA4MDAgcGl0Y2hlcyB0cmFja2VkLgoKCgpgYGB7cn0KZ2NqdTMgPC0gICMjIGRhdGEgZnJvbSBDb2xlJ3MgSnVuZSAzcmQgZ2FtZQogIGdjb2xlZHQgJT4lCiAgZmlsdGVyKGdhbWVfZGF0ZSA9PSAnMjAyMS0wNi0wMycpCmdjanUzCmBgYAoKCmBgYHtyfQpqdTNhdmcgPC0KICBnY2p1MyU+JQogIHNlbGVjdChwaXRjaF9uYW1lLCByZWxlYXNlX3NwaW5fcmF0ZSwgcmVsZWFzZV9zcGVlZCkgJT4lCiAgZ3JvdXBfYnkocGl0Y2hfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z3NwZWVkID0gbWVhbihyZWxlYXNlX3NwZWVkLCBuYS5ybSA9IFRSVUUpLCBhdmdzcGluID0gbWVhbihyZWxlYXNlX3NwaW5fcmF0ZSwgbmEucm0gPSBUUlVFKSwgY291bnQgPSBuKCkpICU+JQogIGFycmFuZ2UocGl0Y2hfbmFtZSkKanUzYXZnCmBgYAoKCldlIGNhbiBzZWUgdGhhdCBmcm9tIENvbGUncyBKdW5lIDNyZCBnYW1lLCB0aGUgcGl0Y2hlcyB3aXRoIHRoZSBoaWdoZXN0IHNwZWVkIHdlcmUgdGhlIGZhc3RiYWxsLCBzaW5rZXIsIGNoYW5nZXVwLCBhbmQgc2xpZGVyLiBBbmQgaGlzIHBpdGNoZXMgd2l0aCB0aGUgaGlnaGVzdCBzcGluIHJhdGVzIHdlcmUgdGhlIGtudWNrbGUgY3VydmUsIHNsaWRlciwgZmFzdGJhbGwsIGFuZCBzaW5rZXIsIHdpdGggYWxsIGJlaW5nIGF0IGxlYXN0IDEwMCBycG0gYWJvdmUgdGhlIGxlYWd1ZSBhdmVyYWdlIG9mIDIyODAgcnBtLgoKCkNvbGUncyBtb3N0IHV0aWxpemVkIHBpdGNoZXMgZHVyaW5nIHRoaXMgZ2FtZToKCiogRmFzdGJhbGwgKGhpZ2ggdmVsb2NpdHkgJiBoaWdoIHNwaW4gcmF0ZSkKCiogS251Y2tsZSBDdXJ2ZSAobWVkaXVtIHZlbG9jaXR5ICYgaGlnaCBzcGluIHJhdGUpCgoqIENoYW5nZXVwIChoaWdoIHZlbG9jaXR5ICYgbG93IHNwaW4gcmF0ZSkKCgpub3RlOiBDb2xlJ3MgRVJBIGR1cmluZyBmcm9tIHRoaXMgZ2FtZSB3YXMgMi4yNiBbQmFzZWJhbGwgUmVmZXJlbmNlXShodHRwczovL3d3dy5iYXNlYmFsbC1yZWZlcmVuY2UuY29tL2JveGVzL05ZQS9OWUEyMDIxMDYwMzAuc2h0bWwpCgoKYGBge3J9CmdjamwxNyA8LQogIGdjb2xlZHQgJT4lCiAgZmlsdGVyKGdhbWVfZGF0ZSA9PSAnMjAyMS0wNy0xNycpCmdjamwxNwpgYGAKCgoKYGBge3J9CmpsMTdhdmcgPC0KICBnY2psMTcgJT4lCiAgZ3JvdXBfYnkocGl0Y2hfbmFtZSkgJT4lCiAgc2VsZWN0KHBpdGNoX25hbWUsIHJlbGVhc2Vfc3Bpbl9yYXRlLCByZWxlYXNlX3NwZWVkKSAlPiUKICBzdW1tYXJpc2UoYXZnc3BpbiA9IG1lYW4ocmVsZWFzZV9zcGluX3JhdGUsIG5hLnJtID0gVFJVRSksIGF2Z3NwZWVkID0gbWVhbihyZWxlYXNlX3NwZWVkLCBuYS5ybSA9IFRSVUUpLCBjb3VudCA9IG4oKSkgJT4lCiAgYXJyYW5nZShwaXRjaF9uYW1lKQpqbDE3YXZnCmBgYAoKCkhlcmUgd2UgY2FuIHNlZSB0aGF0IGZyb20gQ29sZSdzIEp1bHkgMTd0aCBnYW1lLCB0aGUgcGl0Y2hlcyB3aXRoIHRoZSBoaWdoZXN0IHNwZWVkIHdlcmUgdGhlIGZhc3RiYWxsLCBjaGFuZ2V1cCwgYW5kIHNsaWRlci4gQW5kIGhpcyBwaXRjaGVzIHdpdGggdGhlIGhpZ2hlc3Qgc3BpbiByYXRlcyB3ZXJlIHRoZSBrbnVja2xlIGN1cnZlLCBzbGlkZXIsIGFuZCBmYXN0YmFsbCwgYWxsIHN0aWxsIHdlbGwgYWJvdmUgdGhlIGxlYWd1ZSBhdmVyYWdlIG9mIDIyODAgcnBtLgoKCkNvbGUncyBtb3N0IHV0aWxpemVkIHBpdGNoZXMgZHVyaW5nIHRoaXMgZ2FtZToKCiogRmFzdGJhbGwgKGhpZ2ggdmVsb2NpdHkgJiBtZWRpdW0gc3BpbiByYXRlKQoqIEtudWNrbGUgQ3VydmUgKG1lZGl1bSB2ZWxvY2l0eSAmIGhpZ2ggc3BpbiByYXRlKQoqIFNsaWRlciAobWVkaXVtIHZlbG9jaXR5ICYgaGlnaCBzcGluIHJhdGUpCgpub3RlOiBDb2xlJ3MgRVJBIGR1cmluZyBmcm9tIHRoaXMgZ2FtZSB3YXMgMi42MyBbQmFzZWJhbGwgUmVmZXJlbmNlXShodHRwczovL3d3dy5iYXNlYmFsbC1yZWZlcmVuY2UuY29tL2JveGVzL05ZQS9OWUEyMDIxMDcxNzAuc2h0bWwpCgoKYGBge3J9CmdjanUzZ3IgPC0KICBnY2p1MyAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZWxlYXNlX3NwZWVkLCB5ID0gcmVsZWFzZV9zcGluX3JhdGUsIGNvbG9yID0gcGl0Y2hfbmFtZSkpICsKICBnZW9tX3BvaW50KHN0YXQgPSAnaWRlbnRpdHknKSArCiAgeGxhYignUmVsZWFzZSBTcGVlZCAobXBoKScpICsKICB5bGFiKCdSZWxlYXNlIFNwaW4gUmF0ZSAocnBtKScpICsKICBsYWJzKHRpdGxlID0gIkdlcnJpdCBDb2xlJ3MgU3BpbiBSYXRlIGJ5IFBpdGNoIiwKICAgICAgIGNhcHRpb24gPSAnRnJvbSB0aGUgZ2FtZSBwaXRjaGVkIG9uIEp1bmUgM3JkJywKICAgICAgIGNvbG9yID0gJ1BpdGNoIFR5cGUnKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygnNC1TZWFtIEZhc3RiYWxsJyA9ICdjaG9jb2xhdGUxJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQ2hhbmdldXAnID0gJ2Rhcmtnb2xkZW5yb2QxJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnS251Y2tsZSBDdXJ2ZScgPSAnZGFya3NlYWdyZWVuMycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1NpbmtlcicgPSAnZGFya29yY2hpZDEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdTbGlkZXInID0gJ2RlZXBza3libHVlJykpCmdjanUzZ3IKCgpnY2psMTdnciA8LQogIGdjamwxNyAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZWxlYXNlX3NwZWVkLCB5ID0gcmVsZWFzZV9zcGluX3JhdGUsIGNvbG9yID0gcGl0Y2hfbmFtZSkpICsKICBnZW9tX3BvaW50KHN0YXQgPSAnaWRlbnRpdHknKSArCiAgeGxhYignUmVsZWFzZSBTcGVlZCAobXBoKScpICsKICB5bGFiKCdSZWxlYXNlIFNwaW4gUmF0ZSAocnBtKScpICsKICBsYWJzKHRpdGxlID0gIkdlcnJpdCBDb2xlJ3MgU3BpbiBSYXRlIGJ5IFBpdGNoIFR5cGUiLAogICAgICAgY2FwdGlvbiA9ICdGcm9tIHRoZSBnYW1lIENvbGUgcGl0Y2hlZCBvbiBKdWx5IDE3dGgnLAogICAgICAgY29sb3IgPSAnUGl0Y2ggVHlwZScpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygnNC1TZWFtIEZhc3RiYWxsJyA9ICdjaG9jb2xhdGUxJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQ2hhbmdldXAnID0gJ2Rhcmtnb2xkZW5yb2QxJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnS251Y2tsZSBDdXJ2ZScgPSAnZGFya3NlYWdyZWVuMycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1NsaWRlcicgPSAnZGVlcHNreWJsdWUnKSkKZ2NqbDE3Z3IKYGBgCgpXaGVuIGNvbXBhcmluZyB0aGUgdHdvIGdyYXBocyB0aGUgY2hhbmdlIGluIENvbGUncyBzcGluIHJhdGVzIGlzbid0IGFzIGRyYXN0aWMgYXMgQmF1ZXIncy4gSGlzIGNoYW5nZXVwLCBmYXN0YmFsbCwgYW5kIHNsaWRlciByZW1haW5lZCByZWxhdGl2ZWx5IHNpbWlsYXIgdG8gd2hhdCB0aGV5IHdlcmUgZHVyaW5nIGhpcyBzdGFydHMgZnJvbSBoaXMgZ2FtZXMgcHJpb3IgdG8gaW1wbGVtZW50YXRpb24uIEFkZGl0aW9uYWxseSwgdGhlIHNwaW4gb24gaGlzIGN1cnZlYmFsbCBpbmNyZWFzZWQsIG5lYXJseSByZWFjaGluZyAzMDAwIHJwbSBkdXJpbmcgYXQgYmF0IG51bWJlciA0MC4gSGlzIGF2ZXJhZ2UgcmVsZWFzZSB2ZWxvY2l0aWVzIGFsc28gc3RheWVkIHJlbGF0aXZlbHkgc2ltaWxhci4gQWx0aG91Z2ggaGlzIEVSQSBkaWQgZ28gdXAgYnkgMC40IGJldHdlZW4gdGhlc2UgdHdvIGdhbWVzLCB3aGljaCBpcyBhIGhpZ2ggaW5jcmVhc2UgdG8gaW5jdXIgd2l0aGluIGEgbW9udGggYW5kIGEgaGFsZi4KCgojIyMjIENvbGUncyBTdGlja3kgVmVyZGljdDogdWggd2VsbC4uLiAocHJvYmFibHkpIE5PVCBHVUlMVFkKCiMjIEphY29iIGRlR3JvbQoKSmFjb2IgZGVHcm9tIGlzIGFyZ3VhYmx5IG9uZSBvZiB0aGUgYmVzdCBwaXRjaGVycyBpbiBhbGwgb2YgYmFzZWJhbGwuIFdpdGggdHdvIEN5IFlvdW5nIGF3YXJkcywgYSBzZWFzb24gRVJBIG9mIDEuMDgsIGEgc2Vhc29uIFdBUiBvZiA1LjAgKGFzIG9mIEp1bHkgMjl0aCwgMjAyMSksIGFuZCBjb25zaWRlcmluZyBoZSB3YXMgYSBzaG9ydHN0b3AgaW4gY29sbGVnZSwgdGhlcmUgaXMgbm8gZG91YnQgdGhhdCBoZSBpcyBhIGdpZnRlZCBwbGF5ZXIuIEZvbGxvd2luZyBhbGwgb2YgaGlzIHN0ZWxsYXIgcGVyZm9ybWFuY2VzIHRoaXMgc2Vhc29uLCBJIHdhcyB3b25kZXJpbmcgaWYgaGUgaGFkIGFueSBjaGFuZ2UgaW4gcGl0Y2hpbmcgb3V0cHV0LgoKCmBgYHtyfQpkZ3N0YXRzIDwtCiAgcmVhZC5jc3YoJ2RlR3JvbSBBZHZhbmNlZCBTdGF0cy5jc3YnKQpkZ3N0YXRzCmBgYAoKYGBge3J9Cmw4ciA8LQogIGRnc3RhdHMgJT4lCiAgZ3JvdXBfYnkocGl0Y2hfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKQpsOHIKYGBgCgoKCgpgYGB7cn0Kc3RwZyA8LQogIGRnc3RhdHMgJT4lCiAgc2VsZWN0KGdhbWVfZGF0ZSwgcmVsZWFzZV9zcGluX3JhdGUsIHBpdGNoX25hbWUpICU+JQogIGdyb3VwX2J5KGdhbWVfZGF0ZSwgcGl0Y2hfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z3NwaW4gPSBtZWFuKHJlbGVhc2Vfc3Bpbl9yYXRlKSwgcGl0Y2hfbmFtZSwgZ2FtZV9kYXRlKSU+JQogICNncm91cF9ieShwaXRjaF9uYW1lLCBnYW1lX2RhdGUpICU+JQogIHN1bW1hcmlzZShhdmdzcGluLCBwaXRjaF9uYW1lLCBnYW1lX2RhdGUpICU+JQogIG11dGF0ZShkYXRlID0gZGF0ZShnYW1lX2RhdGUpKSAlPiUKICBmaWx0ZXIocGl0Y2hfbmFtZSAhPSAoJ0N1cnZlYmFsbCcpKSAlPiUKICBmaWx0ZXIocGl0Y2hfbmFtZSAhPSAoJ0NoYW5nZXVwJykpCnN0cGcgCm5wIDwtIHN0cGdbIWR1cGxpY2F0ZWQoc3RwZyksXQpucApgYGAKCgpgYGB7cn0KaWRreWV0IDwtCiAgbnAgJT4lCiAgZ2dwbG90KGFlcyhmaWxsID0gZmN0X3JldihwaXRjaF9uYW1lKSwgeSA9IGF2Z3NwaW4sIHggPSBkYXRlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gJ3N0YWNrJywgc3RhdCA9ICdpZGVudGl0eScpICsKICB4bGFiKCdHYW1lIERhdGUnKSArCiAgeWxhYignQXZlcmFnZSBTcGluIFJhdGUgYnkgUGl0Y2gnKQppZGt5ZXQKYGBgCgoKCgojIyBHYXJyZXR0IFJpY2hhcmRzCgpHYXJyZXR0IFJpY2hhcmRzJywgQm9zdG9uJ3MgbmV3ZXN0IHBpdGNoZXIgaGFzIGhhZCBhIHZlcnkgW3dvcmRdIHNlYXNvbiBzbyBmYXIuLi4KCmBgYHtyfQpncmljaGR0IDwtICAjIyBHYXJyZXR0IFJpY2hhcmRzIGRhdGEgZnJvbSBCYXNlYmFsbCBTYXZhbnQKICByZWFkLmNzdignR2FycmV0dCBSaWNoYXJkcyBhZHZhbmNlZCBzdGF0cy5jc3YnKQpncmljaGR0CmBgYAoKCmBgYHtyfQpncmNvdW50cyA8LQogIGdyaWNoZHQgJT4lCiAgZ3JvdXBfYnkocGl0Y2hfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKQpncmNvdW50cwpgYGAKCkhlcmUgd2UgY2FuIHNlZSB0aGF0IFJpY2hhcmRzJyBtb3N0IHV0aWxpemVkIHBpdGNoIGlzIGhpcyBmYXN0YmFsbCB3aXRoIG92ZXIgOTAwIGFwcGVhcmFuY2VzIHdpdGhpbiBiZXR3ZWVuIE1heSA4dGggYW5kIEp1bHkgOXRoLCBmb2xsb3dlZCBieSBoaXMgc2xpZGVyIGFuZCBjdXJ2ZWJhbGwuIFdoZXJlYXMgaGUgcmFyZWx5IHRocmV3IGNoYW5nZXVwIGFuZCBzaW5rZXJzLCBvbmx5IGJlaW5nIHVzZWQgMzMgYW5kIDYgdGltZXMgcmVzcGVjdGl2ZWx5LgoKCmBgYHtyfQpncmp1bDkgPC0gICMjIGZpbHRlcmluZyB0aGUgZGF0YSBmcm9tIEdhcnJldHQgUmljaGFyZCdzIG1vc3QgcmVjZW50IGdhbWUKICBncmljaGR0ICU+JQogIGZpbHRlcihnYW1lX2RhdGUgPT0gJzIwMjEtMDctMDknKQpncmp1bDkKYGBgCgoKYGBge3J9Cmp1bDlhdmdzIDwtICAjI2F2ZXJhZ2VzIGZyb20gSnVseSA5dGggZ2FtZQogIGdyanVsOSU+JQogIHNlbGVjdChwaXRjaF9uYW1lLCByZWxlYXNlX3NwaW5fcmF0ZSwgcmVsZWFzZV9zcGVlZCkgJT4lCiAgZ3JvdXBfYnkocGl0Y2hfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z3NwZWVkID0gbWVhbihyZWxlYXNlX3NwZWVkLCBuYS5ybSA9IFRSVUUpLCBhdmdzcGluID0gbWVhbihyZWxlYXNlX3NwaW5fcmF0ZSwgbmEucm0gPSBUUlVFKSwgY291bnQgPSBuKCkpCmp1bDlhdmdzCmBgYAoKSGVyZSB3ZSBjYW4gc2VlIHRoYXQgZnJvbSBSaWNoYXJkcycgSnVseSA5dGggZ2FtZSwgdGhlIHBpdGNoZXMgd2l0aCB0aGUgaGlnaGVzdCBzcGVlZHMgd2VyZSB0aGUgZmFzdGJhbGwgYW5kIGNoYW5nZXVwLiBBbmQgaGlzIHBpdGNoZXMgd2l0aCB0aGUgaGlnaGVzdCBzcGluIHJhdGVzIHdlcmUgdGhlIGN1cnZlYmFsbCwgc2xpZGVyLCBhbmQgZmFzdGJhbGwsIGFsbCBhYm92ZSB0aGUgbGVhZ3VlIGF2ZXJhZ2Ugb2YgMjI4MCBycG0uCgoKUmljaGFyZHMnIG1vc3QgdXRpbGl6ZWQgcGl0Y2hlcyBkdXJpbmcgdGhpcyBnYW1lOgoKKiBGYXN0YmFsbCAoaGlnaCB2ZWxvY2l0eSAmIG1lZGl1bSBzcGluIHJhdGUpCgoqIEN1cnZlYmFsbCAobG93IHZlbG9jaXR5ICYgaGlnaCBzcGluIHJhdGUpCgoqIFNsaWRlciAobWVkaXVtIHZlbG9jaXR5ICYgaGlnaCBzcGluIHJhdGUpCgpub3RlOiBSaWNoYXJkcycgRVJBIGR1cmluZyBmcm9tIHRoaXMgZ2FtZSB3YXMgNC45MSBbQmFzZWJhbGwgUmVmZXJlbmNlXShodHRwczovL3d3dy5iYXNlYmFsbC1yZWZlcmVuY2UuY29tL2JveGVzL0JPUy9CT1MyMDIxMDcwOTAuc2h0bWwpCgpgYGB7cn0KZ3JtYXk4IDwtICAjIyBmaWx0ZXJpbmcgdGhlIGRhdGEgZnJvbSBSaWNoYXJkJ3MgTWF5IDh0aCBnYW1lCiAgZ3JpY2hkdCAlPiUKICBmaWx0ZXIoZ2FtZV9kYXRlID09ICcyMDIxLTA1LTA4JykKZ3JtYXk4CmBgYAoKCmBgYHtyfQptYXk4YXZncyA8LQogIGdybWF5OCU+JQogIHNlbGVjdChyZWxlYXNlX3NwaW5fcmF0ZSwgcmVsZWFzZV9zcGVlZCwgcGl0Y2hfbmFtZSkgJT4lCiAgZ3JvdXBfYnkocGl0Y2hfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z3NwZWVkID0gbWVhbihyZWxlYXNlX3NwZWVkLCBuYS5ybSA9IFRSVUUpLCBhdmdzcGluID0gbWVhbihyZWxlYXNlX3NwaW5fcmF0ZSwgbmEucm0gPSBUUlVFKSwgY291bnQgPSBuKCkpCm1heThhdmdzCmBgYAoKRHVyaW5nIFJpY2hhcmRzJyBNYXkgOHRoIGdhbWUsIGl0IGNhbiBzZWVuIGhlIG9ubHkgdXRpbGl6ZWQgdGhyZWUgZGlmZmVyZW50IHR5cGVzIG9mIHBpdGNoZXMuIFRoZSB0d28gd2l0aCB0aGUgaGlnaGVzdCBzcGVlZHMgd2VyZSB0aGUgZmFzdGJhbGwgYW5kIHNsaWRlci4gVGhlIHR3byBwaXRjaCB0eXBlcyB3aXRoIHRoZSBoaWdoZXN0IHNwaW4gcmF0ZXMgd2VyZSB0aGUgY3VydmViYWxsIGFuZCBzbGlkZXIuIE5vdGUgYWxsIG9mIGhpcyBhdmVyYWdlIHNwaW4gcmF0ZXMgZnJvbSB0aGlzIGdhbWUgd2hpY2ggd2VyZSBzaWduaWZpY2FudGx5IGFib3ZlIHRoZSBsZWFndWUgYXZlcmFnZSBvZiAyMjgwIHJwbS4KCgpSaWNoYXJkcycgbW9zdCB1dGlsaXplZCBwaXRjaGVzIGR1cmluZyB0aGlzIGdhbWU6CgoqIEZhc3RiYWxsIChoaWdoIHZlbG9jaXR5ICYgaGlnaCBzcGluIHJhdGUpCgoqIFNsaWRlciAobWVkaXVtIHZlbG9jaXR5ICYgaGlnaCBzcGluIHJhdGUpCgoqIEN1cnZlYmFsbCAobG93IHZlbG9jaXR5ICYgaGlnaCBzcGluIHJhdGUpCgpub3RlOiBSaWNoYXJkcycgRVJBIGR1cmluZyBmcm9tIHRoaXMgZ2FtZSB3YXMgNC41NCBbQmFzZWJhbGwgUmVmZXJlbmNlXShodHRwczovL3d3dy5iYXNlYmFsbC1yZWZlcmVuY2UuY29tL2JveGVzL0JBTC9CQUwyMDIxMDUwODAuc2h0bWwpCgpgYGB7cn0KbXk4Z3IgPC0KICBncm1heTglPiUKICBnZ3Bsb3QoYWVzKHggPSByZWxlYXNlX3NwZWVkLCB5ID0gcmVsZWFzZV9zcGluX3JhdGUsIGNvbG9yID0gcGl0Y2hfbmFtZSkpKwogIGdlb21fcG9pbnQoKSArCiAgeGxhYignUmVsZWFzZSBTcGVlZCAobXBoKScpKwogIHlsYWIoJ1NwaW4gUmF0ZSAocnBtKScpICsKICBsYWJzKHRpdGxlID0gJ0dlcnJpdHQgUmljaGFyZHMgU3BpbiBSYXRlIGJ5IFBpdGNoJywKICAgICAgIGNvbG9yID0gJ1BpdGNoIFR5cGUnLAogICAgICAgY2FwdGlvbiA9ICdGcm9tIGdhbWUgcGl0Y2hlZCBvbiBNYXkgOHRoJykgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCc0LVNlYW0gRmFzdGJhbGwnID0gJ2Nob2NvbGF0ZTEnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDdXJ2ZWJhbGwnID0gJ2N5YW4zJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnU2xpZGVyJyA9ICdkYXJrb3JjaGlkMicpKQpteThncgoKZ3JqdWw5Z3IgPC0KICBncmp1bDkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVsZWFzZV9zcGVlZCwgeSA9IHJlbGVhc2Vfc3Bpbl9yYXRlLCBjb2xvciA9IHBpdGNoX25hbWUpKSArCiAgZ2VvbV9wb2ludCgpICsKICB4bGFiKCdSZWxlYXNlIFNwZWVkIChtcGgpJykgKwogIHlsYWIoJ1JlbGVhc2UgU3BpbiBSYXRlJykgKwogIGxhYnModGl0bGUgPSAnR2Vycml0dCBSaWNoYXJkcyBTcGluIFJhdGUgYnkgUGl0Y2gnLAogICAgICAgY2FwdGlvbiA9ICdGb3IgZ2FtZSBwaXRjaGVkIG9uIEp1bHkgOXRoJywKICAgICAgIGNvbG9yID0gJ1BpdGNoIFR5cGUnKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoJzQtU2VhbSBGYXN0YmFsbCcgPSAnY2hvY29sYXRlMScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0NoYW5nZXVwJyA9ICdjaGFydHJldXNlMycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0N1cnZlYmFsbCcgPSAnY3lhbjMnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdTbGlkZXInID0gJ2RhcmtvcmNoaWQyJykpCmdyanVsOWdyCmBgYAoKCldoZW4gZXhhbWluaW5nIFJpY2hhcmRzJyBwaXRjaCB2ZWxvY2l0aWVzIGFuZCBzcGluIHJhdGVzIGJldHdlZW4gdGhlc2UgdHdvIGdhbWVzIHRoZXJlIGlzIGEgY2xlYXIgZGlmZmVyZW5jZSBpbiBwZXJmb3JtYW5jZS4gR2VuZXJhbGx5LCBoaXMgcGl0Y2hlcyBhcmUgbW9yZSBjb25jZW50cmF0ZWQgaW4gdGhlIEp1bHkgZ2FtZSwgc2hvd2luZyB0aGF0IHRoZXJlJ3MgbW9yZSBjb25zaXN0ZW5jeSBiZXR3ZWVuIHRoZSBwaXRjaGVzIGhlIHdhcyB0aHJvd2luZyBpbiBKdWx5IHRoYW4gaW4gTWF5LiBSaWNoYXJkcycgd2VudCBmcm9tIGhhdmluZyBtb3JlIHRoYW4gaGFsZiBvZiBoaXMgY3VydmViYWxscyBhYm92ZSAzMzAwIHJwbSBpbiBNYXkgdG8gbm90IGV2ZW4gaGF2aW5nIGEgc2luZ2xlIGN1cnZlYmFsbCByZWFjaCAzMDAwIHJwbS4gV2hlbiBjb21wYXJpbmcgdGhlIGF2ZXJhZ2VzIHRoZXJlJ3MgYmVlbiBhIGRyb3Agb2YgNDEwIHJwbSBpbiB0aGlzIHBpdGNoIGFuZCBhIDQuMjUgbXBoIGRyb3AgaW4gdmVsb2NpdHkuIFdoZW4gbG9va2luZyBhdCBoaXMgc2xpZGVycywgdGhlIHNwaW4gcmF0ZXMgYXJlIGNvbmNlbnRyYXRlZCBhcm91bmQgMjkwMCBycG0sIHdoaWNoIHRoZW4gZHJvcHBlZCB0byBhcm91bmQgMjYwMCBycG0uIFRoZSB2ZWxvY2l0eSBjaGFuZ2Ugd2l0aCB0aGlzIHBpdGNoIHdhc24ndCBhcyBkcmFzdGljIHNoaWZ0aW5nIHdpdGggYW4gYXZlcmFnZSBvZiBhYm91dCAxLjkgbXBoLCB3aGljaCB3b3VsZG4ndCBiZSB2ZXJ5IHN1c3BpY2lvdXMgaWYgbm90IGZvciB0aGUgb3RoZXIgY2hhbmdlcy4gQWRkaXRpb25hbGx5LCB3aGVuIGxvb2tpbmcgYXQgaGlzIGZhc3RiYWxscyAoaGlzIG1vc3QgdXRpbGl6ZWQgcGl0Y2gpIHRoZXJlIGlzbid0IGFzIHNpZ25pZmljYW50IG9mIGEgY2hhbmdlLiBUaGUgdmVsb2NpdGllcyBhcmUgY29uY2VudHJhdGVkIGluIHRoZSBzYW1lIGFyZWEgYW5kIG9ubHkgaGFkIGEgY2hhbmdlIGluIDAuNDUgbXBoLiBUaGUgYXZlcmFnZSBzcGluIHJhdGVzIGZvciB0aGUgZmFzdGJhbGwgb25seSBkcm9wcGVkIGJ5IDE3NSBycG0sIHdoaWNoIGJ5IGl0c2VsZiBpc24ndCBwYXJ0aWN1bGFybHkgc3VzcGljaW91cy4gWWV0IHdoZW4gbG9va2luZyBhdCBhbGwgb2YgdGhlIGNoYW5nZXMgaW4gUmljaGFyZHMnIHBpdGNoZXMgYW5kIGhpcyBnYW1lIHNwZWNpZmljIEVSQSBpbmNyZWFzaW5nIGJ5IDAuNjMgdGhlcmUgaXMgbW9yZSB0aGFuIGFtcGxlIGV2aWRlbmNlIHRoYXQgUmljaGFyZHMnIHdhcyBpbiBmYWN0IHV0aWxpemluZyBzdGlja3kgc3Vic3RhbmNlcy4KCgoKIyMjIyAgUmljaGFyZHMnIFN0aWNreSBWZXJkaWN0OiBHVUlMVFkKCgoKCgoK